﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

//added
using System.IO.IsolatedStorage;
using System.IO;
using Microsoft.Phone.Notification;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Microsoft.Phone.Shell;
using PhoneApp1;
using PhoneApp1.GeocoderService;
using System.Data;
using PhoneApp1.ServiceReference1;
using Microsoft.Phone.Net.NetworkInformation;
using System.Text;
using System.Device.Location;

namespace TaxiTouchClient
{
    public partial class Client_accueil : PhoneApplicationPage
    {
        PhoneApp1.Client client;
        bool subscribed;
        GeocodeResult locationDestination;
        GeocodeResult locationOrigine;
        GeoCoordinateWatcher geoWatcher;

        PhoneApp1.ServiceReference1.Service1Client myService;

        //URI for this app's notification channel.
        HttpNotificationChannel myPushChannel;

        //constructeur
        public Client_accueil()
        {
            InitializeComponent();

            myService = new PhoneApp1.ServiceReference1.Service1Client();
            Valider_ClientAccueil.IsEnabled = true;
            Annuler_ClientAccueil.IsEnabled = false;
            subscribed = false;

            client = new PhoneApp1.Client();

            IsolatedStorageSettings storage = IsolatedStorageSettings.ApplicationSettings;
            if (storage.Contains("clientDestination"))
            {
                locationDestination = (GeocodeResult) storage["clientDestination"];
                txtRecapDest.Text = locationDestination.DisplayName;
                //MessageBox.Show(Convert.ToDecimal(locationDestination.Locations[0].Latitude).ToString());
            }
            else
            {
                Valider_ClientAccueil.IsEnabled = false;
            }

            if (storage.Contains("LocalisationClient"))
            {
                locationOrigine = (GeocodeResult)storage["LocalisationClient"];
                txtRecapDepart.Text = locationOrigine.DisplayName;
                //MessageBox.Show(Convert.ToDecimal(locationOrigine.Locations[0].Latitude).ToString());
            }
            else
            {
                Valider_ClientAccueil.IsEnabled = false;
            }

            if (storage.Contains("stateClientDemande"))
            {
                int idEtat = (int)storage["stateClientDemande"];
                switch (idEtat)
                {
                    case 0: txtRecapStatut.Text = "Demande non envoyée"; break;
                    case 1: txtRecapStatut.Text = "En attente de taxi..."; 
                        Valider_ClientAccueil.IsEnabled = false; 
                        Annuler_ClientAccueil.IsEnabled = true;
                        break;
                    case 2: txtRecapStatut.Text = "Prise en charge";
                        Valider_ClientAccueil.IsEnabled = false;
                        Annuler_ClientAccueil.IsEnabled = true;
                        break;
                    case 3: txtRecapStatut.Text = "Course clôturée"; break;
                    case 4: txtRecapStatut.Text = "Course annulée"; break;
                }
            }
            else
            {
                txtRecapStatut.Text = "Demande non envoyée";
                IsolatedStorageSettings.ApplicationSettings["stateClientDemande"] = 0;
            }

            myPushChannel = HttpNotificationChannel.Find("myChannel");

            if (myPushChannel == null)
            {
                rawmessage.Text += " Channel was null.";
                //This channel needs to be created. ChannelUriUpdated will fire upon completion.
                myPushChannel = new HttpNotificationChannel("myChannel"); //create, then attach delegates, then Open()
                attachHandlerFunctions();
                myPushChannel.Open(); // will not fire ChannelUriUpdated if no handler is wired up first!
                if (!myPushChannel.IsShellToastBound)
                {
                    myPushChannel.BindToShellToast();
                }
            }
            else
            {
                rawmessage.Text += " Channel was found!";
                //ChannelUriUpdated is not going to fire. Call subscribing method on web service. Attach delegates.
                attachHandlerFunctions();
                myService.SubscribeMyPhoneAsync(client.getDeviceID(), myPushChannel.ChannelUri.ToString());
            }
        }

        #region Notifications Push
        
        void attachHandlerFunctions()
        {
            //attaches delegates to push channel events

            //if error, print onscreen
            myPushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(myPushChannel_ErrorOccurred);

            //After call to SubscribeMyPhone completes, notify of success
            myService.SubscribeMyPhoneCompleted += new EventHandler<SubscribeMyPhoneCompletedEventArgs>(myClient_SubscribeMyPhoneCompleted);

            //ChannelUriUpdated fires when channel is first created or the channel URI changes 
            myPushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(myPushChannel_ChannelUriUpdated);

            myPushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(myPushChannel_ShellToastNotificationReceived);

            //Handle raw push notifications, which are received only while app is running.
            myPushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(myPushChannel_HttpNotificationReceived);
        }

        void myPushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
        {
            /*Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show("ahbon");
                if (e.Collection != null)
                {
                    Dictionary<string, string> collection = (Dictionary<string, string>)e.Collection;
                    //ShellToast toast = new ShellToast();
                    //toast.Title = collection["wp:Text1"];
                    //toast.Content = collection["wp:Text2"];
                    MessageBox.Show(collection["wp:Text1"] + " " + collection["wp:Text2"]);
                }
            });   
            */
            StringBuilder message = new StringBuilder();
            string relativeUri = string.Empty;

            message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());

            // Parse out the information that was part of the message.
            foreach (string key in e.Collection.Keys)
            {
                message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);

                if (string.Compare(
                    key,
                    "wp:Param",
                    System.Globalization.CultureInfo.InvariantCulture,
                    System.Globalization.CompareOptions.IgnoreCase) == 0)
                {
                    relativeUri = e.Collection[key];
                }
            }

            // Display a dialog of all the fields in the toast.
            Dispatcher.BeginInvoke(() => MessageBox.Show(message.ToString()));
        }

        void myPushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
        {
            //Fires from shell thread, so updates to UI have to use dispatcher's BeginInvoke() method.
            //The body of the notification is a stream, per the MPNS standard, but we know it's just text
            //per our web service design, so here we just decode, and display.
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                //this will fire in UI thread
                StreamReader myReader = new StreamReader(e.Notification.Body);
                rawmessage.Text = "Received Raw Notification: " + myReader.ReadToEnd();
            });
        }

        void myPushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {
            //also fires in notification thread. There are a couple things we want to do here, once we know we 
            //have a valid channel from MPNS. 
            // 1) Make sure phone's shell knows this channel is authorized to receive Tile updates when app is not running.
            if (myPushChannel.IsShellTileBound == false)
            {
                var ListOfAllowedDomains = new Collection<Uri> {
                    // Lists domains that can send tile updates and so forth as push notifications. 
                    // Only these authorized domains will be allowed by the shell to push new tiles to the phone
                    new Uri(@"http://taxitouch.cloudapp.net") // e.g. if you published a webservice at http://foo.com/service1.svc -- put "http://foo.com" here.
                };

                //Register this channel with the shell, pass on authorized domain in way method expects
                myPushChannel.BindToShellTile(ListOfAllowedDomains);
            }

            //2) Make sure phone's shell knows this channel is authorized to receive Toast messages when app is not running
            if (myPushChannel.IsShellToastBound == false)
            {
                myPushChannel.BindToShellToast();
            }
            //3) Show that this event fired onscreen.
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                rawmessage.Text = "uri updated";
            });

            //4) Pass the new ChannelUri on to the subscription service.
            myService.SubscribeMyPhoneAsync(client.getDeviceID(), myPushChannel.ChannelUri.ToString());
        }


        void myClient_SubscribeMyPhoneCompleted(object sender, SubscribeMyPhoneCompletedEventArgs e)
        {
            //Handles completion of call to SubscribeMyPhone() on web service
            if (e.Error == null)
            {
                // no server-side error occurred
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    subscriptionStatus.Text = "Subscribed!";
                    subscribed = true;
                    IsolatedStorageSettings.ApplicationSettings["idClient"] = e.Result.IDClient;
                });
            }
            else
            {
                //show error onscreen
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show(e.Error.Message);
                });
            }

            //As a last step, since we know at this point that we will have a valid ChannelUri, print its value onscreen.
            //Don't do this in real life, obviously. Here, it's just to show how MPNS works.
            //channelURITextBlock.Text = myPushChannel.ChannelUri.ToString();
        }

        void myPushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
        {
            //handles channel error caused from indirect exception
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                subscriptionStatus.Text = e.Message;
            });
        }

        
        #endregion

        private void Destination_ClientAccueil_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Pages/Client_destination.xaml",UriKind.Relative));
        }

        private void Geolocaliser_ClientAccueil_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Pages/Client_geo_auto.xaml", UriKind.Relative));
        }

        private void TaxiPassword_GotFocus(object sender, RoutedEventArgs e)
        {
            if (taxiPassword.Password == "Password")
            {
                taxiPassword.Password = "";
            }
        }

        private void TaxiPassword_LostFocus(object sender, RoutedEventArgs e)
        {
            if (taxiPassword.Password == "")
            {
                taxiPassword.Password = "Password";
            }
        }

        private void Valider_ClientAccueil_Click(object sender, RoutedEventArgs e)
        {
            if(subscribed)
            {
                IsolatedStorageSettings storage = IsolatedStorageSettings.ApplicationSettings;
                int idEtat = (int)storage["stateClientDemande"];
                if (idEtat == 2)
                {
                    //cloture de la demande
                    MessageBox.Show("La demande a été clôturée");
                    txtRecapStatut.Text = "Aucune demande en cours";
                    txtRecapDepart.Text = "";
                    txtRecapDest.Text = "";
                }
                else
                {
                    if (storage.Contains("clientDestination")
                    && storage.Contains("LocalisationClient"))
                    {
                        MessageBoxResult res = MessageBox.Show("Veuillez confirmer votre demande", "Confirmation", MessageBoxButton.OKCancel);
                        if (res == MessageBoxResult.OK)
                        {
                            myService.InsertDemandeClientCompleted += new EventHandler<InsertDemandeClientCompletedEventArgs>(insertDemandeCompleted);
                            myService.InsertDemandeClientAsync(Convert.ToInt32(storage["idClient"]),
                                        locationOrigine.Locations[0].Longitude, locationOrigine.Locations[0].Latitude,
                                        locationOrigine.DisplayName,
                                        locationDestination.Locations[0].Longitude, locationDestination.Locations[0].Latitude,
                                        locationDestination.DisplayName,
                                        Convert.ToInt32(storage["clientDestinationNb"])
                            );
                        }
                    }
                }             
            }
            else MessageBox.Show("Vous ne pouvez envoyer votre demande en raison d'un problème de connexion avec le serveur");
        }

        void insertDemandeCompleted(object sender, InsertDemandeClientCompletedEventArgs e)
        {
            if (e.Result)
            {
                MessageBox.Show("Demande envoyée avec succès");
                txtRecapStatut.Text = "En attente de taxi...";
                //Valider_ClientAccueil.Content = "Cloturer la demande";
                Valider_ClientAccueil.IsEnabled = false;
                Annuler_ClientAccueil.IsEnabled = true;
                IsolatedStorageSettings.ApplicationSettings["stateClientDemande"] = 1; //en attente
            }
        }

        private void Annuler_ClientAccueil_Click(object sender, RoutedEventArgs e)
        {
            /* TO DO ANNULATIONNNNNNNNNNNN */
            //myService.UpdateEtatDemandeClientCompleted += new EventHandler<UpdateEtatDemandeClientCompletedEventArgs>(myService_UpdateEtatDemandeClientCompleted);
            //myService.UpdateEtatDemandeClientAsync(0, 4);
        }

        void myService_UpdateEtatDemandeClientCompleted(object sender, UpdateEtatDemandeClientCompletedEventArgs e)
        {
            MessageBox.Show("annulée");
        }

        private void Valider_TaxiLogin_Click(object sender, RoutedEventArgs e)
        {
            if (taxiPassword.Password != "")
            {
                geoWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
                geoWatcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(geoWatcher_StatusChanged);
                geoWatcher.Start();
                //MessageBox.Show(geoWatcher.Position.Location.Latitude.ToString());

                if (IsolatedStorageSettings.ApplicationSettings.Contains("Taxi"))
                {
                    //connexion
                    myService.ConnectTaxiCompleted += new EventHandler<ConnectTaxiCompletedEventArgs>(myService_ConnectTaxiCompleted);
                    myService.ConnectTaxiAsync(client.getDeviceID(),taxiPassword.Password,
                        Convert.ToDecimal(geoWatcher.Position.Location.Longitude),
                        Convert.ToDecimal(geoWatcher.Position.Location.Latitude));
                }
                else
                {
                    // insertion
                    myService.InsertTaxiCompleted += new EventHandler<InsertTaxiCompletedEventArgs>(myService_InsertTaxiCompleted);
                    myService.InsertTaxiAsync(client.getDeviceID(), myPushChannel.ChannelUri, taxiPassword.Password,
                        Convert.ToDecimal(geoWatcher.Position.Location.Longitude),
                        Convert.ToDecimal(geoWatcher.Position.Location.Latitude));
                }
            }
            else MessageBox.Show("Veuillez entrez votre mot de passe");
        }

        void myService_ConnectTaxiCompleted(object sender, ConnectTaxiCompletedEventArgs e)
        {
            IsolatedStorageSettings.ApplicationSettings["Taxi"] = e.Result;
            NavigationService.Navigate(new Uri("/Pages/Taxi_accueil.xaml", UriKind.Relative));
        }

        void myService_InsertTaxiCompleted(object sender, InsertTaxiCompletedEventArgs e)
        {
            IsolatedStorageSettings.ApplicationSettings["Taxi"] = e.Result;
            NavigationService.Navigate(new Uri("/Pages/Taxi_accueil.xaml", UriKind.Relative));
        }

        void geoWatcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                    // le gps n'est pas activé
                    break;
                case GeoPositionStatus.Initializing:
                    // le gps est en cours d'initialisation
                    break;
                case GeoPositionStatus.NoData:
                    // il n'y a pas d'informations
                    break;
                case GeoPositionStatus.Ready:
                    // le GPS est activé et disponible
                    break;
            }
        }

        private void refresh_Click(object sender, RoutedEventArgs e)
        {
            //myService.SelectADemandeClientCompleted += new EventHandler<SelectADemandeClientCompletedEventArgs>(myService_SelectADemandeClientCompleted);
            //myService.SelectADemandeClientAsync(18);
            txtRecapStatut.Text = "Demande prise en charge";
            IsolatedStorageSettings.ApplicationSettings["stateClientDemande"] = 2;
            Valider_ClientAccueil.IsEnabled = true;
            Valider_ClientAccueil.Content = "Cloturer la demande";
        }

        void myService_SelectADemandeClientCompleted(object sender, SelectADemandeClientCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                switch (e.Result.ID_Etat)
                {
                    case 1: txtRecapStatut.Text = "En attente de taxi..."; break;
                    case 2: txtRecapStatut.Text = "Prise en charge"; break;
                    case 3: txtRecapStatut.Text = "Course clôturée"; break;
                    case 4: txtRecapStatut.Text = "Course annulée"; break;
                }
                IsolatedStorageSettings.ApplicationSettings["stateClientDemande"] = e.Result.ID_Etat;
            }
        }
    }
}